#include "rtdb.h"

CRTDB::CRTDB(int iBattStackNum/*电池堆*/, int iBANum/*BA数,100个通用输入寄存器, 50个保持寄存器*/, int iBattBankNum/*电池组数*/, QObject *parent)
	: QObject(parent)
{
	m_iBattStackNum = iBattStackNum;
	m_iBANum = iBANum;
	m_iBattBankNum = iBattBankNum;	
	m_pRTDBData = 0;

	if (m_iBattStackNum <= 0)
	{
		emit addLog(RUN_LOG_FAILED, ("The param iBattStackNum <= 0, Set iBattStackNum = 1"));
		m_iBattStackNum = 1;
	}

	if (m_iBattBankNum <= 0)
	{
		emit addLog(RUN_LOG_FAILED, ("The param iBattBankNum <= 0, Set iBattBankNum = 1"));
		m_iBattBankNum = 1;
	}

	if (m_iBANum <= 0)
	{
		emit addLog(RUN_LOG_FAILED, ("The param iBANum <= 0, Set iBattBankNum = 1"));
		m_iBANum = 1;
	}

	// init some variables
	m_pSharedMemery = new QSharedMemory(("KGDZ_RTDB_BAMS"), parent);
}

CRTDB::~CRTDB()
{
	if (m_pSharedMemery)
	{
		delete m_pSharedMemery;
		m_pSharedMemery = 0;
	}
}

//  1 - Create RTDB OK
//  2 - Open RTDB OK
// -1 - FAILED
// -2 - RTDB has been created or opened
int CRTDB::initRTDB(bool bReadWrite)
{
	int iRetVal = -1;
	QSharedMemory::AccessMode mode = QSharedMemory::ReadOnly;

	if(m_pRTDBData)
	{
		emit addLog(RUN_LOG_FAILED, ("RTDB has been created or opened."));
		iRetVal = -2;
	}

	if (bReadWrite)
	{
		mode = QSharedMemory::ReadWrite;

		if (m_pSharedMemery->create(m_iBattStackNum * sizeof(CBattStack) + m_iBANum * sizeof(CBAComReg) + m_iBattBankNum * sizeof(CBattBank) + m_iBattBankNum * sizeof(CBankAlarm), mode))
		{
			emit addLog(RUN_LOG_FAILED, QString(("Create RTDB(BattStackNum = %1, BANum = %2, BattBankNum = %3) OK.")).arg(m_iBattStackNum).arg(m_iBANum).arg(m_iBattBankNum));

			m_pRTDBData = (char*)m_pSharedMemery->data();
			memset(m_pRTDBData, 0, m_iBattStackNum * sizeof(CBattStack) + m_iBANum * sizeof(CBAComReg) + m_iBattBankNum * sizeof(CBattBank) + m_iBattBankNum * sizeof(CBankAlarm));

			iRetVal = 1;
		}
	}

	if (iRetVal < 0) // 创建失败 或者 只读
	{
		// have existed	
		if (m_pSharedMemery->attach(mode))
		{
			emit addLog(RUN_LOG_FAILED, ("Open RTDB OK."));

			m_pRTDBData = (char*)m_pSharedMemery->data();
			iRetVal = 2;
		}		
		else
		{
			emit addLog(RUN_LOG_FAILED, ("Init RTDB FAILED. Err Inof:") + m_pSharedMemery->errorString());
		}
	}

	return iRetVal;
}

// -1 - 找不到寄存器
//  0 - OK
int CRTDB::getComInputRegValBA(int iBAIndex, quint16 usRegAddr, quint16& usVal)
{
	if (iBAIndex < 0 || iBAIndex >= m_iBANum || !m_pRTDBData || usRegAddr > 100 || usRegAddr < 1)
	{
		return -1;
	}

	CBAComReg* pBAComReg = (CBAComReg*)(m_pRTDBData + m_iBattStackNum * sizeof(CBattStack) + iBAIndex * sizeof(CBAComReg));
	if (pBAComReg)
	{
		usVal = pBAComReg->usComInputRegVal[usRegAddr - 1];

		return 0;
	}

	return -1;
}

// -1 - 找不到寄存器
//  0 - OK
int CRTDB::getComHoldRegValBA(int iBAIndex, quint16 usRegAddr, quint16& usVal)
{
	if (iBAIndex < 0 || iBAIndex >= m_iBANum || !m_pRTDBData || usRegAddr > 100 || usRegAddr < 1)
	{
		return -1;
	}

	CBAComReg* pBAComReg = (CBAComReg*)(m_pRTDBData + m_iBattStackNum * sizeof(CBattStack) + iBAIndex * sizeof(CBAComReg));
	if (pBAComReg)
	{
		usVal = pBAComReg->usComHoldRegVal[usRegAddr - 1];

		return 0;
	}

	return -1;
}

CBattStack* CRTDB::getStack(int iBattStackIndex)
{
	if (iBattStackIndex < 0 || iBattStackIndex >= m_iBattStackNum || !m_pRTDBData)
	{
		return 0;
	}

	return (CBattStack*)(m_pRTDBData + sizeof(CBattStack) * iBattStackIndex);
}

CBattBank* CRTDB::getBank(int iBattBankIndex)
{
	if (iBattBankIndex < 0 || iBattBankIndex >= m_iBattBankNum || !m_pRTDBData)
	{
		return 0;
	}

	return (CBattBank*)(m_pRTDBData + sizeof(CBattStack) * m_iBattStackNum + sizeof(CBAComReg) * m_iBANum + sizeof(CBattBank) * iBattBankIndex);
}

CBAComReg* CRTDB::getBAComReg(int iBAIndex)
{
	if (iBAIndex < 0 || iBAIndex >= m_iBANum || !m_pRTDBData)
	{
		return 0;
	}

	return (CBAComReg*)(m_pRTDBData + sizeof(CBattStack) * m_iBattStackNum + sizeof(CBAComReg) * iBAIndex);
}

// Alarm
CBankAlarm* CRTDB::getBankAlarm(int iBattBankIndex)
{
	if (iBattBankIndex < 0 || iBattBankIndex >= m_iBattBankNum || !m_pRTDBData)
	{
		return 0;
	}

	return (CBankAlarm*)(m_pRTDBData + sizeof(CBattStack) * m_iBattStackNum + sizeof(CBAComReg) * m_iBANum + sizeof(CBattBank) * m_iBattBankNum + sizeof(CBankAlarm) * iBattBankIndex);
}

SAlarm* CRTDB::getFirstAlarm(int iBattBankIndex)
{
	return getFirstAlarm(getBankAlarm(iBattBankIndex));
}

SAlarm* CRTDB::getFirstAlarm(CBankAlarm* pBankAlarm)
{
	if (!pBankAlarm)
	{
		return 0;
	}

	quint16 usFirstNo = pBankAlarm->usFirstAlarmNo; 

	if (ALARM_LAST_NO == usFirstNo || usFirstNo >= BANK_ALARM_MAX_NUM)
	{
		return 0;
	}

	return &(pBankAlarm->bankAlarm[usFirstNo]);
}

SAlarm* CRTDB::getAlarm(CBankAlarm* pBankAlarm, quint16 usNo)
{
	if (!pBankAlarm || ALARM_LAST_NO == usNo || usNo >= BANK_ALARM_MAX_NUM)
	{
		return 0;
	}

	return &(pBankAlarm->bankAlarm[usNo]);
}

SAlarmParam* CRTDB::getAlarmParam(int iBattBankIndex)
{
	SAlarmParam* pParam = 0;
	CBankAlarm* pBankAlarm = getBankAlarm(iBattBankIndex);
	if (pBankAlarm)
	{
		pParam = &(pBankAlarm->param);
	}

	return pParam;
}

void CRTDB::setDryWetCtrl(CBattBank* pBattBank, quint16 usDry1Ctrl, quint16 usDry2Ctrl, quint16 usDry3Ctrl, quint16 usDry4Ctrl, quint16 usWetCtrl, int iDry1CtrlNum, int iDry2CtrlNum, int iDry3CtrlNum, int iDry4CtrlNum, int iWetCtrlNum)
{
	setDryCtrl1(pBattBank, usDry1Ctrl, usDry2Ctrl, iDry1CtrlNum, iDry2CtrlNum);
	setDryCtrl2(pBattBank, usDry3Ctrl, usDry4Ctrl, iDry3CtrlNum, iDry4CtrlNum);
	setWetCtrl(pBattBank, usWetCtrl, iWetCtrlNum);
}

void CRTDB::setDryCtrl1(CBattBank* pBattBank, quint16 usDry1Ctrl, quint16 usDry2Ctrl, int iDry1CtrlNum, int iDry2CtrlNum)
{
	if (pBattBank)
	{
		if (iDry1CtrlNum != 0)
		{
			pBattBank->usDry1Ctrl = usDry1Ctrl;
			pBattBank->iDry1CtrlNum = iDry1CtrlNum;
		}
		
		if (iDry2CtrlNum != 0)
		{
			pBattBank->usDry2Ctrl = usDry2Ctrl;
			pBattBank->iDry2CtrlNum = iDry2CtrlNum;
		}
	}
}

void CRTDB::setDryCtrl2(CBattBank* pBattBank, quint16 usDry3Ctrl, quint16 usDry4Ctrl, int iDry3CtrlNum, int iDry4CtrlNum)
{
	if (pBattBank)
	{
		if (iDry3CtrlNum != 0)
		{
			pBattBank->usDry3Ctrl = usDry3Ctrl;
			pBattBank->iDry3CtrlNum = iDry3CtrlNum;
		}

		if (iDry4CtrlNum != 0)
		{
			pBattBank->usDry4Ctrl = usDry4Ctrl;
			pBattBank->iDry4CtrlNum = iDry4CtrlNum;
		}
	}
}

void CRTDB::setWetCtrl(CBattBank* pBattBank, quint16 usWetCtrl, int iWetCtrlNum)
{
	if (pBattBank)
	{
		if (iWetCtrlNum != 0)
		{
			pBattBank->usWetCtrl = usWetCtrl;
			pBattBank->iWetCtrlNum = iWetCtrlNum;
		}	
	}
}

